using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;

namespace Sage.Data.Extensions
{
    /// <summary>
    /// 提供字符串类型的扩展方法，主要用于简化字符串判空、类型转换、编码解码、路径处理等常用操作。
    /// </summary>
    /// <remarks>
    /// 此类包含针对<see cref="string"/>类型的扩展方法，使字符串相关操作更加简洁和直观。
    /// 所有方法都是线程安全的，可以在多线程环境中使用。
    /// </remarks>
    public static partial class StringExtensions
    {
        #region 空值检查和默认值处理

        /// <summary>
        /// 判断字符串是否为null、空字符串或仅包含空白字符。
        /// </summary>
        /// <param name="value">要检查的字符串。</param>
        /// <returns>
        /// 如果字符串为null、空字符串("")或仅包含空白字符，则返回true；否则返回false。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "";
        /// bool isEmpty = text.IsEmpty(); // 返回 true
        /// 
        /// string text2 = "  ";
        /// bool isEmpty2 = text2.IsEmpty(); // 返回 true
        /// 
        /// string text3 = "Hello";
        /// bool isEmpty3 = text3.IsEmpty(); // 返回 false
        /// 
        /// string text4 = null;
        /// bool isEmpty4 = text4.IsEmpty(); // 返回 true
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用<see cref="string.IsNullOrWhiteSpace(string)"/>实现，可以检测null、空字符串和仅包含空格、制表符等空白字符的字符串。
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool IsEmpty(this string? value)
        {
            return string.IsNullOrWhiteSpace(value);
        }

        /// <summary>
        /// 判断字符串是否为null或空字符串。
        /// </summary>
        /// <param name="value">要检查的字符串。</param>
        /// <returns>
        /// 如果字符串为null或空字符串("")，则返回true；否则返回false。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "";
        /// bool isNullOrEmpty = text.IsNullOrEmpty(); // 返回 true
        /// 
        /// string text2 = "  ";
        /// bool isNullOrEmpty2 = text2.IsNullOrEmpty(); // 返回 false，因为包含空格
        /// 
        /// string text3 = "Hello";
        /// bool isNullOrEmpty3 = text3.IsNullOrEmpty(); // 返回 false
        /// 
        /// string text4 = null;
        /// bool isNullOrEmpty4 = text4.IsNullOrEmpty(); // 返回 true
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用<see cref="string.IsNullOrEmpty(string)"/>实现，与<see cref="IsEmpty"/>方法的区别在于：
        /// <list type="bullet">
        /// <item><description><see cref="IsNullOrEmpty"/>不会将仅包含空白字符的字符串视为空</description></item>
        /// <item><description><see cref="IsEmpty"/>会将仅包含空白字符的字符串视为空</description></item>
        /// </list>
        /// 根据业务需求选择合适的方法。
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool IsNullOrEmpty(this string? value)
        {
            return string.IsNullOrEmpty(value);
        }

        /// <summary>
        /// 返回字符串或当字符串为空时返回默认值。
        /// </summary>
        /// <param name="value">要检查的字符串。</param>
        /// <param name="defaultValue">当字符串为空时返回的默认值。</param>
        /// <returns>原字符串或默认值。</returns>
        /// <example>
        /// <code>
        /// string text = null;
        /// string result = text.DefaultIfEmpty("N/A"); // 返回 "N/A"
        /// 
        /// string text2 = "Hello";
        /// string result2 = text2.DefaultIfEmpty("N/A"); // 返回 "Hello"
        /// </code>
        /// </example>
        public static string DefaultIfEmpty(this string? value, string defaultValue)
        {
            return value.IsEmpty() ? defaultValue : value!;
        }

        #endregion

        #region 类型转换

        /// <summary>
        /// 尝试将字符串转换为整型(int)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符，提取连续的数字部分进行转换。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的整数值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "123";
        /// int result = text.ToInt(); // 返回 123
        /// 
        /// string text2 = "a123b";
        /// int result2 = text2.ToInt(); // 返回 123
        /// 
        /// string text3 = "abc";
        /// int result3 = text3.ToInt(); // 返回 0
        /// int result4 = text3.ToInt(10); // 返回 10
        /// 
        /// string text4 = null;
        /// int result5 = text4.ToInt(); // 返回 0
        /// </code>
        /// </example>
        public static int ToInt(this string? value, int defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',') // 允许数字中有逗号作为千位分隔符
                    break; // 一旦遇到非数字且已经有数字了，就停止（处理"a123b"的情况）
            }
            if (digits.Length == 0)
                return defaultValue;
            return int.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为长整型(long)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的长整型值，或在转换失败时返回默认值。</returns>
        public static long ToLong(this string? value, long defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',')
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return long.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为短整型(short)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的短整型值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "123";
        /// short result = text.ToShort(); // 返回 123
        /// 
        /// string text2 = "99999"; // 超出short范围
        /// short result2 = text2.ToShort(-1); // 返回 -1（默认值）
        /// 
        /// string text3 = "abc";
        /// short result3 = text3.ToShort(); // 返回 0
        /// </code>
        /// </example>
        public static short ToShort(this string? value, short defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',')
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return short.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为字节型(byte)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的字节值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "255";
        /// byte result = text.ToByte(); // 返回 255
        /// 
        /// string text2 = "256"; // 超出byte范围
        /// byte result2 = text2.ToByte(100); // 返回 100（默认值）
        /// 
        /// string text3 = "50abc";
        /// byte result3 = text3.ToByte(); // 返回 50
        /// </code>
        /// </example>
        public static byte ToByte(this string? value, byte defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0)
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return byte.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为有符号字节型(sbyte)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符，支持负数。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的有符号字节值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "127";
        /// sbyte result = text.ToSByte(); // 返回 127
        /// 
        /// string text2 = "-128";
        /// sbyte result2 = text2.ToSByte(); // 返回 -128
        /// 
        /// string text3 = "200"; // 超出sbyte范围
        /// sbyte result3 = text3.ToSByte(-1); // 返回 -1（默认值）
        /// </code>
        /// </example>
        public static sbyte ToSByte(this string? value, sbyte defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;

            // 处理负号
            var cleanValue = value!.Trim();
            var isNegative = cleanValue.StartsWith('-');
            if (isNegative)
                cleanValue = cleanValue[1..];

            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in cleanValue)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0)
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;

            var numberStr = (isNegative ? "-" : "") + digits.ToString();
            return sbyte.TryParse(numberStr, out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为无符号整型(uint)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的无符号整数值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "4294967295";
        /// uint result = text.ToUInt(); // 返回 4294967295
        /// 
        /// string text2 = "123abc456";
        /// uint result2 = text2.ToUInt(); // 返回 123
        /// 
        /// string text3 = "-123"; // 负数
        /// uint result3 = text3.ToUInt(100); // 返回 100（默认值）
        /// </code>
        /// </example>
        public static uint ToUInt(this string? value, uint defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',')
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return uint.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为无符号长整型(ulong)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的无符号长整型值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "18446744073709551615";
        /// ulong result = text.ToULong(); // 返回最大ulong值
        /// 
        /// string text2 = "123abc";
        /// ulong result2 = text2.ToULong(); // 返回 123
        /// </code>
        /// </example>
        public static ulong ToULong(this string? value, ulong defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',')
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return ulong.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为无符号短整型(ushort)，如果转换失败则返回默认值。
        /// 自动处理字符串中的非数字字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的无符号短整型值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "65535";
        /// ushort result = text.ToUShort(); // 返回 65535
        /// 
        /// string text2 = "100000"; // 超出ushort范围
        /// ushort result2 = text2.ToUShort(1000); // 返回 1000（默认值）
        /// </code>
        /// </example>
        public static ushort ToUShort(this string? value, ushort defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 提取连续的数字字符
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
                else if (digits.Length > 0 && c != ',')
                    break;
            }
            if (digits.Length == 0)
                return defaultValue;
            return ushort.TryParse(digits.ToString(), out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为单精度浮点型(float)，如果转换失败则返回默认值。
        /// 支持不同的小数点表示法和科学计数法。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0.0f。</param>
        /// <returns>转换后的单精度浮点值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "123.45";
        /// float result = text.ToSingle(); // 返回 123.45f
        /// 
        /// string text2 = "123,45"; // 欧洲数字格式
        /// float result2 = text2.ToSingle(); // 返回 123.45f
        /// 
        /// string text3 = "1.23E+2";
        /// float result3 = text3.ToSingle(); // 返回 123.0f
        /// 
        /// string text4 = "abc";
        /// float result4 = text4.ToSingle(); // 返回 0.0f
        /// </code>
        /// </example>
        public static float ToSingle(this string? value, float defaultValue = 0.0f)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 尝试兼容不同区域的小数点表示
            var formattedValue = value!.Replace(',', '.');

            return float.TryParse(formattedValue,
                System.Globalization.NumberStyles.Any,
                System.Globalization.CultureInfo.InvariantCulture,
                out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为双精度浮点型(double)，如果转换失败则返回默认值。
        /// 支持不同的小数点表示法和科学计数法。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0.0。</param>
        /// <returns>转换后的双精度浮点值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "123.45";
        /// double result = text.ToDouble(); // 返回 123.45
        /// 
        /// string text2 = "123,45"; // 欧洲数字格式
        /// double result2 = text2.ToDouble(); // 返回 123.45
        /// 
        /// string text3 = "abc";
        /// double result3 = text3.ToDouble(); // 返回 0.0
        /// 
        /// string text4 = "1.23E+2";
        /// double result4 = text4.ToDouble(); // 返回 123.0
        /// </code>
        /// </example>
        public static double ToDouble(this string? value, double defaultValue = 0.0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 尝试兼容不同区域的小数点表示
            var formattedValue = value!.Replace(',', '.');

            return double.TryParse(formattedValue,
                System.Globalization.NumberStyles.Any,
                System.Globalization.CultureInfo.InvariantCulture,
                out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为十进制数(decimal)，如果转换失败则返回默认值。
        /// 适用于财务和货币计算。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为0。</param>
        /// <returns>转换后的十进制值，或在转换失败时返回默认值。</returns>
        public static decimal ToDecimal(this string? value, decimal defaultValue = 0)
        {
            if (value.IsEmpty())
                return defaultValue;
            // 尝试兼容不同区域的小数点表示
            var formattedValue = value!.Replace(',', '.');

            return decimal.TryParse(formattedValue,
                System.Globalization.NumberStyles.Any,
                System.Globalization.CultureInfo.InvariantCulture,
                out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为字符(char)，如果转换失败则返回默认值。
        /// 如果字符串包含多个字符，则返回第一个字符。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为'\0'。</param>
        /// <returns>转换后的字符值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "A";
        /// char result = text.ToChar(); // 返回 'A'
        /// 
        /// string text2 = "Hello";
        /// char result2 = text2.ToChar(); // 返回 'H'（第一个字符）
        /// 
        /// string text3 = "";
        /// char result3 = text3.ToChar('X'); // 返回 'X'（默认值）
        /// 
        /// string text4 = "123";
        /// char result4 = text4.ToChar(); // 返回 '1'
        /// </code>
        /// </example>
        public static char ToChar(this string? value, char defaultValue = '\0')
        {
            if (value.IsEmpty())
                return defaultValue;

            return value![0];
        }

        /// <summary>
        /// 尝试将字符串转换为布尔值(bool)，如果转换失败则返回默认值。
        /// 支持多种表示"真"值的字符串形式。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为false。</param>
        /// <returns>转换后的布尔值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "true";
        /// bool result = text.ToBool(); // 返回 true
        /// 
        /// string text2 = "1";
        /// bool result2 = text2.ToBool(); // 返回 true
        /// 
        /// string text3 = "yes";
        /// bool result3 = text3.ToBool(); // 返回 true
        /// 
        /// string text4 = "no";
        /// bool result4 = text4.ToBool(); // 返回 false
        /// </code>
        /// </example>
        public static bool ToBool(this string? value, bool defaultValue = false)
        {
            if (value.IsEmpty())
                return defaultValue;
            value = value!.Trim().ToLowerInvariant();

            return value switch
            {
                "true" or "1" or "yes" or "y" or "on" => true,
                "false" or "0" or "no" or "n" or "off" => false,
                _ => defaultValue
            };
        }

        /// <summary>
        /// 尝试将字符串转换为日期时间(DateTime)，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为DateTime.MinValue。</param>
        /// <returns>转换后的日期时间值，或在转换失败时返回默认值。</returns>
        public static DateTime ToDateTime(this string? value, DateTime? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? DateTime.MinValue;
            return DateTime.TryParse(value, out var result) ? result : defaultValue ?? DateTime.MinValue;
        }

        /// <summary>
        /// 尝试将字符串转换为时间间隔(TimeSpan)，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。支持格式如"1.23:45:56"、"23:45:56"、"45:56"等。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为TimeSpan.Zero。</param>
        /// <returns>转换后的时间间隔值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "1.23:45:56";
        /// TimeSpan result = text.ToTimeSpan(); // 返回 1天23小时45分56秒
        /// 
        /// string text2 = "23:45:56";
        /// TimeSpan result2 = text2.ToTimeSpan(); // 返回 23小时45分56秒
        /// 
        /// string text3 = "45:56";
        /// TimeSpan result3 = text3.ToTimeSpan(); // 返回 45分56秒
        /// 
        /// string text4 = "invalid";
        /// TimeSpan result4 = text4.ToTimeSpan(); // 返回 TimeSpan.Zero
        /// </code>
        /// </example>
        public static TimeSpan ToTimeSpan(this string? value, TimeSpan? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? TimeSpan.Zero;
            return TimeSpan.TryParse(value, out var result) ? result : defaultValue ?? TimeSpan.Zero;
        }

#if NET6_0_OR_GREATER
        /// <summary>
        /// 尝试将字符串转换为仅日期(DateOnly)，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为DateOnly.MinValue。</param>
        /// <returns>转换后的仅日期值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "2024-01-15";
        /// DateOnly result = text.ToDateOnly(); // 返回 2024年1月15日
        /// 
        /// string text2 = "01/15/2024";
        /// DateOnly result2 = text2.ToDateOnly(); // 返回 2024年1月15日
        /// 
        /// string text3 = "invalid date";
        /// DateOnly result3 = text3.ToDateOnly(); // 返回 DateOnly.MinValue
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法仅在.NET 6.0及更高版本中可用。
        /// </remarks>
        public static DateOnly ToDateOnly(this string? value, DateOnly? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? DateOnly.MinValue;
            return DateOnly.TryParse(value, out var result) ? result : defaultValue ?? DateOnly.MinValue;
        }

        /// <summary>
        /// 尝试将字符串转换为仅时间(TimeOnly)，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为TimeOnly.MinValue。</param>
        /// <returns>转换后的仅时间值，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "14:30:25";
        /// TimeOnly result = text.ToTimeOnly(); // 返回 下午2:30:25
        /// 
        /// string text2 = "2:30 PM";
        /// TimeOnly result2 = text2.ToTimeOnly(); // 返回 下午2:30:00
        /// 
        /// string text3 = "invalid time";
        /// TimeOnly result3 = text3.ToTimeOnly(); // 返回 TimeOnly.MinValue
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法仅在.NET 6.0及更高版本中可用。
        /// </remarks>
        public static TimeOnly ToTimeOnly(this string? value, TimeOnly? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? TimeOnly.MinValue;
            return TimeOnly.TryParse(value, out var result) ? result : defaultValue ?? TimeOnly.MinValue;
        }
#endif

        /// <summary>
        /// 尝试将字符串转换为版本号(Version)，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。支持格式如"1.0"、"1.2.3"、"1.2.3.4"等。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为new Version(0, 0)。</param>
        /// <returns>转换后的版本号，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "1.2.3.4";
        /// Version result = text.ToVersion(); // 返回 Version(1, 2, 3, 4)
        /// 
        /// string text2 = "2.0";
        /// Version result2 = text2.ToVersion(); // 返回 Version(2, 0)
        /// 
        /// string text3 = "invalid version";
        /// Version result3 = text3.ToVersion(); // 返回 Version(0, 0)
        /// 
        /// string text4 = "3.1.0";
        /// Version result4 = text4.ToVersion(new Version(1, 0)); // 返回 Version(3, 1, 0)
        /// </code>
        /// </example>
        public static Version ToVersion(this string? value, Version? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? new Version(0, 0);
            return Version.TryParse(value, out var result) ? result : defaultValue ?? new Version(0, 0);
        }

        /// <summary>
        /// 尝试将字符串转换为URI，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为null。</param>
        /// <returns>转换后的URI，或在转换失败时返回默认值。</returns>
        /// <example>
        /// <code>
        /// string text = "https://www.example.com";
        /// Uri result = text.ToUri(); // 返回对应的Uri对象
        /// 
        /// string text2 = "ftp://files.example.com/folder";
        /// Uri result2 = text2.ToUri(); // 返回FTP Uri对象
        /// 
        /// string text3 = "invalid url";
        /// Uri result3 = text3.ToUri(); // 返回 null
        /// 
        /// string text4 = "not a url";
        /// Uri fallback = new Uri("http://localhost");
        /// Uri result4 = text4.ToUri(fallback); // 返回 fallback Uri
        /// </code>
        /// </example>
        public static Uri? ToUri(this string? value, Uri? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue;
            return Uri.TryCreate(value, UriKind.Absolute, out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为枚举值，如果转换失败则返回默认值。
        /// </summary>
        /// <typeparam name="TEnum">枚举类型。</typeparam>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="ignoreCase">是否忽略大小写，默认为true。</param>
        /// <param name="defaultValue">转换失败时返回的默认值。</param>
        /// <returns>转换后的枚举值，或在转换失败时返回默认值。</returns>
        /// <remarks>
        /// 此方法在AOT编译模式下可能需要额外配置以支持泛型。
        /// </remarks>
        public static TEnum ToEnum<TEnum>(this string? value, bool ignoreCase = true, TEnum defaultValue = default)
            where TEnum : struct, Enum
        {
            if (value.IsEmpty())
                return defaultValue;
            return Enum.TryParse<TEnum>(value, ignoreCase, out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 尝试将字符串转换为Guid，如果转换失败则返回默认值。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <param name="defaultValue">转换失败时返回的默认值，默认为Guid.Empty。</param>
        /// <returns>转换后的Guid值，或在转换失败时返回默认值。</returns>
        public static Guid ToGuid(this string? value, Guid? defaultValue = null)
        {
            if (value.IsEmpty())
                return defaultValue ?? Guid.Empty;
            return Guid.TryParse(value, out var result) ? result : defaultValue ?? Guid.Empty;
        }

        #endregion

        #region 编码解码

        /// <summary>
        /// 将字符串中的 Unicode 转义序列（如 \u4E2D）转换为对应的字符
        /// 高性能版本：使用 Span 和手动解析，避免正则表达式开销
        /// </summary>
        /// <param name="input">包含 Unicode 转义序列的字符串</param>
        /// <returns>转义后的字符串</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static string UnescapeUnicode(this string input)
        {
            if (string.IsNullOrEmpty(input))
                return input;
            // 快速检查：如果没有 \u 就直接返回
            if (!input.Contains("\\u"))
                return input;
            return UnescapeUnicodeCore(input);
        }
        private static string UnescapeUnicodeCore(string input)
        {
            var inputSpan = input.AsSpan();
            var sb = new StringBuilder(input.Length);

            for (int i = 0; i < inputSpan.Length; i++)
            {
                if (inputSpan[i] == '\\' && i + 5 < inputSpan.Length && inputSpan[i + 1] == 'u')
                {
                    // 检查接下来的4个字符是否都是有效的十六进制
                    var hexSpan = inputSpan.Slice(i + 2, 4);
                    if (TryParseHex(hexSpan, out var unicode))
                    {
                        sb.Append((char)unicode);
                        i += 5; // 跳过整个 \uxxxx 序列
                    }
                    else
                    {
                        sb.Append(inputSpan[i]);
                    }
                }
                else
                {
                    sb.Append(inputSpan[i]);
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 高性能十六进制解析，避免异常和字符串分配
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool TryParseHex(ReadOnlySpan<char> hex, out int result)
        {
            result = 0;

            for (int i = 0; i < hex.Length; i++)
            {
                var c = hex[i];
                int digit;

                if (c >= '0' && c <= '9')
                    digit = c - '0';
                else if (c >= 'A' && c <= 'F')
                    digit = c - 'A' + 10;
                else if (c >= 'a' && c <= 'f')
                    digit = c - 'a' + 10;
                else
                    return false;

                result = (result << 4) | digit;
            }

            return true;
        }

        /// <summary>
        /// 将字符串转换为 Base64 编码的字符串。
        /// </summary>
        /// <param name="value">要编码的字符串。</param>
        /// <param name="encoding">字符编码，默认为 UTF-8。</param>
        /// <returns>Base64 编码的字符串，如果输入为 null 则返回空字符串。</returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string base64 = text.ToBase64String(); // 返回 "SGVsbG8gV29ybGQ="
        /// </code>
        /// </example>
        public static string ToBase64String(this string? value, Encoding? encoding = null)
        {
            if (value.IsEmpty())
                return string.Empty;

            encoding ??= Encoding.UTF8;
            byte[] bytes = encoding.GetBytes(value!);
            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// 将 Base64 编码的字符串解码为普通字符串。
        /// </summary>
        /// <param name="base64Value">Base64 编码的字符串。</param>
        /// <param name="encoding">字符编码，默认为 UTF-8。</param>
        /// <returns>解码后的字符串，如果输入为 null 则返回空字符串。</returns>
        /// <example>
        /// <code>
        /// string base64 = "SGVsbG8gV29ybGQ=";
        /// string text = base64.FromBase64(); // 返回 "Hello World"
        /// </code>
        /// </example>
        public static string FromBase64(this string? base64Value, Encoding? encoding = null)
        {
            if (base64Value.IsNullOrEmpty())
                return string.Empty;

            try
            {
                encoding ??= Encoding.UTF8;
                byte[] bytes = Convert.FromBase64String(base64Value!);
                return encoding.GetString(bytes);
            }
            catch (FormatException)
            {
                // 处理输入不是有效的 Base64 字符串的情况
                return string.Empty;
            }
        }

        /// <summary>
        /// 将字符串转换为 URL 安全的 Base64 编码字符串。
        /// 标准 Base64 中的 '+', '/' 和 '=' 字符在 URL 中可能需要编码，此方法替换它们为 URL 安全的字符。
        /// </summary>
        /// <param name="value">要编码的字符串。</param>
        /// <param name="encoding">字符编码，默认为 UTF-8。</param>
        /// <returns>URL 安全的 Base64 编码字符串，如果输入为 null 则返回空字符串。</returns>
        /// <example>
        /// <code>
        /// string text = "Hello+World/with=special chars";
        /// string urlSafeBase64 = text.ToUrlSafeBase64(); // 返回不含 +, /, = 的字符串
        /// </code>
        /// </example>
        public static string ToUrlSafeBase64(this string? value, Encoding? encoding = null)
        {
            if (value.IsNullOrEmpty())
                return string.Empty;

            string base64 = value.ToBase64String(encoding);
            return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
        }

        /// <summary>
        /// 将 URL 安全的 Base64 编码字符串解码为普通字符串。
        /// </summary>
        /// <param name="urlSafeBase64Value">URL 安全的 Base64 编码字符串。</param>
        /// <param name="encoding">字符编码，默认为 UTF-8。</param>
        /// <returns>解码后的字符串，如果解码失败则返回空字符串。</returns>
        /// <example>
        /// <code>
        /// string urlSafeBase64 = "SGVsbG8tV29ybGRfd2l0aF9zcGVjaWFsIGNoYXJz";
        /// string text = urlSafeBase64.FromUrlSafeBase64(); // 返回原始字符串
        /// </code>
        /// </example>
        public static string FromUrlSafeBase64(this string? urlSafeBase64Value, Encoding? encoding = null)
        {
            if (urlSafeBase64Value.IsNullOrEmpty())
                return string.Empty;

            try
            {
                // 将 URL 安全的 Base64 转换回标准 Base64
                string base64 = urlSafeBase64Value!.Replace('-', '+').Replace('_', '/');

                // 添加回可能被移除的填充字符 '='
                switch (base64.Length % 4)
                {
                    case 2: base64 += "=="; break;
                    case 3: base64 += "="; break;
                }

                return base64.FromBase64(encoding);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 将 Base64 编码的字符串转换为字节数组。
        /// </summary>
        /// <param name="base64Value">Base64 编码的字符串。</param>
        /// <returns>解码后的字节数组，如果输入为 null 则返回空字节数组。</returns>
        public static byte[] FromBase64ToBytes(this string? base64Value)
        {
            if (base64Value.IsNullOrEmpty())
                return [];

            try
            {
                return Convert.FromBase64String(base64Value!);
            }
            catch (FormatException)
            {
                // 处理输入不是有效的 Base64 字符串的情况
                return [];
            }
        }

        /// <summary>
        /// 将十六进制字符串转换为字节数组
        /// </summary>
        /// <param name="hexString">十六进制编码的字符串</param>
        /// <returns>解码后的字节数组,如果输入为 null 则返回空字节数组。</returns>
        public static byte[] FromHexToBytes(this string? hexString)
        {
            if (hexString.IsNullOrEmpty())
                return [];

            try
            {
                return Convert.FromHexString(hexString!);
            }
            catch (FormatException)
            {
                return [];
            }
        }

        /// <summary>
        /// 对字符串进行URL编码，将特殊字符转换为百分号编码格式。
        /// </summary>
        /// <param name="value">要编码的字符串。</param>
        /// <returns>
        /// URL编码后的字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <remarks>
        /// 内部使用HttpUtility.UrlEncode方法实现。
        /// 适用于构建URL查询参数、表单数据提交等场景。
        /// 注意：需要引用System.Web程序集，或在ASP.NET Core中使用WebUtility.UrlEncode。
        /// </remarks>
        public static string UrlEncode(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return System.Web.HttpUtility.UrlEncode(value!);
        }

        /// <summary>
        /// 对URL编码的字符串进行解码，将百分号编码转换回原始字符。
        /// </summary>
        /// <param name="value">要解码的URL编码字符串。</param>
        /// <returns>
        /// URL解码后的字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <remarks>
        /// 内部使用HttpUtility.UrlDecode方法实现。
        /// 适用于处理URL查询参数、解析表单数据等场景。
        /// 如果输入字符串不是有效的URL编码格式，仍会尝试解码并返回结果。
        /// </remarks>
        public static string UrlDecode(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return System.Web.HttpUtility.UrlDecode(value!);
        }

        #endregion

        #region 哈希计算

        /// <summary>
        /// 计算字符串的MD5哈希值，返回32位小写十六进制字符串。
        /// </summary>
        /// <param name="value">要计算哈希值的字符串。</param>
        /// <returns>
        /// 32位小写十六进制格式的MD5哈希值。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string hash = text.ToMD5String(); // 返回 "b10a8db164e0754105b7a99be72e3fe5"
        /// 
        /// string password = "123456";
        /// string hashedPassword = password.ToMD5String(); // 返回 "e10adc3949ba59abbe56e057f20f883e"
        /// 
        /// string empty = "";
        /// string hash2 = empty.ToMD5String(); // 返回 ""
        /// 
        /// // 用于密码验证
        /// string inputPassword = "123456";
        /// bool isValidPassword = inputPassword.ToMD5String() == storedHashedPassword;
        /// </code>
        /// </example>
        /// <remarks>
        /// 使用UTF-8编码将字符串转换为字节数组后计算MD5哈希。
        /// 返回的哈希值为32位小写十六进制字符串。
        /// 注意：MD5已被认为是密码学上不安全的，不建议用于安全敏感的场景。
        /// 适用于文件完整性校验、简单的数据唯一性标识等场景。
        /// 对于密码存储，建议使用更安全的哈希算法如SHA-256或bcrypt。
        /// </remarks>
        public static string ToMD5String(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;
            var bytes = Encoding.UTF8.GetBytes(value!);
            var hash = System.Security.Cryptography.MD5.HashData(bytes);
            return Convert.ToHexString(hash).ToLowerInvariant();
        }

        /// <summary>
        /// 计算字符串的SHA1哈希值，返回40位小写十六进制字符串。
        /// </summary>
        /// <param name="value">要计算哈希值的字符串。</param>
        /// <returns>
        /// 40位小写十六进制格式的SHA1哈希值。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string hash = text.ToSHA1String(); // 返回 "0a4d55a8d778e5022fab701977c5d840bbc486d0"
        /// 
        /// string password = "mypassword";
        /// string hashedPassword = password.ToSHA1String();
        /// 
        /// // 文件内容校验
        /// string fileContent = File.ReadAllText("config.json");
        /// string contentHash = fileContent.ToSHA1String();
        /// 
        /// // 生成唯一标识
        /// string uniqueKey = $"{userId}_{timestamp}".ToSHA1String();
        /// </code>
        /// </example>
        /// <remarks>
        /// 使用UTF-8编码将字符串转换为字节数组后计算SHA1哈希。
        /// SHA1相比MD5更安全，但仍不建议用于密码存储等安全敏感场景。
        /// 适用于数据完整性校验、缓存键生成、非安全性哈希需求等场景。
        /// </remarks>
        public static string ToSHA1String(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            var bytes = Encoding.UTF8.GetBytes(value!);
            var hash = System.Security.Cryptography.SHA1.HashData(bytes);
            return Convert.ToHexString(hash).ToLowerInvariant();
        }

        /// <summary>
        /// 计算字符串的SHA256哈希值，返回64位小写十六进制字符串。
        /// </summary>
        /// <param name="value">要计算哈希值的字符串。</param>
        /// <returns>
        /// 64位小写十六进制格式的SHA256哈希值。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string hash = text.ToSHA256String(); // 返回 64位哈希值
        /// 
        /// string sensitiveData = "user_secret_key";
        /// string secureHash = sensitiveData.ToSHA256String();
        /// 
        /// // 密码安全存储
        /// string userPassword = "userInput123";
        /// string storedHash = userPassword.ToSHA256String();
        /// 
        /// // 数据指纹生成
        /// string dataFingerprint = jsonData.ToSHA256String();
        /// </code>
        /// </example>
        /// <remarks>
        /// 使用UTF-8编码将字符串转换为字节数组后计算SHA256哈希。
        /// SHA256是目前推荐的安全哈希算法，适用于密码存储、数字签名等安全场景。
        /// 比MD5和SHA1更安全，但计算速度稍慢。
        /// </remarks>
        public static string ToSHA256String(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            var bytes = Encoding.UTF8.GetBytes(value!);
            var hash = System.Security.Cryptography.SHA256.HashData(bytes);
            return Convert.ToHexString(hash).ToLowerInvariant();
        }

        /// 转换为Base64字符串用于传输
        /// <remarks>
        /// 该方法首先将字符串转换为UTF-8字节数组，然后调用字节数组的HMAC-SHA1签名方法。
        /// HMAC-SHA1常用于API签名、Token生成等需要消息认证的场景。
        /// 虽然SHA1已不推荐用于新的安全应用，但HMAC-SHA1在某些兼容性场景下仍被广泛使用。
        /// 返回的字节数组可根据需要转换为Base64、十六进制或其他格式的字符串。
        /// </remarks>
        public static byte[] ToHmacSha1(this string value, string key)
        {
            return ByteExtensions.ToHmacSha1(Encoding.UTF8.GetBytes(value), key);
        }

        #endregion

        #region 字符串操作

        /// <summary>
        /// 截断字符串到指定长度，超出部分用指定后缀替代。
        /// </summary>
        /// <param name="value">要截断的字符串。</param>
        /// <param name="maxLength">最大长度，包含后缀长度。</param>
        /// <param name="suffix">超出时添加的后缀，默认为"..."。</param>
        /// <returns>
        /// 截断后的字符串。如果原字符串长度小于等于最大长度，则返回原字符串；
        /// 否则返回截断后的字符串加上后缀。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "这是一个很长的字符串内容";
        /// string result = text.Truncate(10); // 返回 "这是一个很长的字..."
        /// 
        /// string result2 = text.Truncate(10, "[更多]"); // 返回 "这是一个很[更多]"
        /// 
        /// string shortText = "短文本";
        /// string result3 = shortText.Truncate(10); // 返回 "短文本"（不变）
        /// </code>
        /// </example>
        /// <remarks>
        /// 当maxLength小于等于suffix长度时，直接截断到maxLength，不添加后缀。
        /// 此方法对于显示摘要、列表项等场景非常有用。
        /// </remarks>
        public static string Truncate(this string? value, int maxLength, string suffix = "...")
        {
            if (value.IsEmpty() || value!.Length <= maxLength)
                return value ?? string.Empty;

            if (maxLength <= suffix.Length)
                return value[..maxLength];

            return value[..(maxLength - suffix.Length)] + suffix;
        }

        /// <summary>
        /// 将指定字符串重复指定次数。
        /// </summary>
        /// <param name="value">要重复的字符串。</param>
        /// <param name="count">重复次数，必须大于0。</param>
        /// <returns>
        /// 重复后的字符串。如果输入字符串为空或重复次数小于等于0，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string pattern = "AB";
        /// string result = pattern.Repeat(3); // 返回 "ABABAB"
        /// 
        /// string separator = "-";
        /// string line = separator.Repeat(20); // 返回 "--------------------"
        /// 
        /// string empty = "";
        /// string result2 = empty.Repeat(5); // 返回 ""
        /// 
        /// string result3 = "test".Repeat(0); // 返回 ""
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法适用于生成分隔线、填充字符、测试数据等场景。
        /// 内部使用LINQ的Enumerable.Repeat方法实现，性能较好。
        /// </remarks>
        public static string Repeat(this string? value, int count)
        {
            if (value.IsEmpty() || count <= 0)
                return string.Empty;

            return string.Concat(Enumerable.Repeat(value, count));
        }

        /// <summary>
        /// 反转字符串中字符的顺序。
        /// </summary>
        /// <param name="value">要反转的字符串。</param>
        /// <returns>
        /// 反转后的字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello";
        /// string result = text.Reverse(); // 返回 "olleH"
        /// 
        /// string number = "12345";
        /// string reversed = number.Reverse(); // 返回 "54321"
        /// 
        /// string empty = "";
        /// string result2 = empty.Reverse(); // 返回 ""
        /// 
        /// string result3 = ((string?)null).Reverse(); // 返回 ""
        /// </code>
        /// </example>
        /// <remarks>
        /// 注意：此方法按字符反转，对于包含Unicode代理对的字符串可能不会按预期工作。
        /// 如果需要处理复杂的Unicode字符，建议使用StringInfo类。
        /// </remarks>
        public static string Reverse(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return new string([.. value!.Reverse()]);
        }

        /// <summary>
        /// 从字符串左侧截取指定长度的子字符串。
        /// </summary>
        /// <param name="value">源字符串。</param>
        /// <param name="length">要截取的长度。</param>
        /// <returns>
        /// 左侧的子字符串。如果长度超过字符串长度，则返回整个字符串。
        /// 如果输入为null或空，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string left5 = text.Left(5); // 返回 "Hello"
        /// 
        /// string short = "Hi";
        /// string leftLong = short.Left(10); // 返回 "Hi"（不会异常）
        /// 
        /// // 截取文件名前缀
        /// string fileName = "document_2024_01_15.pdf";
        /// string prefix = fileName.Left(8); // 返回 "document"
        /// 
        /// // 显示摘要
        /// string content = "很长的文章内容...";
        /// string summary = content.Left(50) + "...";
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法不会抛出索引越界异常，超出长度时返回完整字符串。
        /// 常用于字符串截取、显示摘要、数据处理等场景。
        /// </remarks>
        public static string Left(this string? value, int length)
        {
            if (value.IsEmpty() || length <= 0)
                return string.Empty;

            return value!.Length <= length ? value : value[..length];
        }

        /// <summary>
        /// 从字符串右侧截取指定长度的子字符串。
        /// </summary>
        /// <param name="value">源字符串。</param>
        /// <param name="length">要截取的长度。</param>
        /// <returns>
        /// 右侧的子字符串。如果长度超过字符串长度，则返回整个字符串。
        /// 如果输入为null或空，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello World";
        /// string right5 = text.Right(5); // 返回 "World"
        /// 
        /// string fileName = "document.pdf";
        /// string extension = fileName.Right(3); // 返回 "pdf"
        /// 
        /// // 获取文件扩展名
        /// string fullName = "report_2024.xlsx";
        /// string ext = fullName.Right(4); // 返回 "xlsx"
        /// 
        /// // 截取后缀信息
        /// string code = "USER_123456";
        /// string id = code.Right(6); // 返回 "123456"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法不会抛出索引越界异常，超出长度时返回完整字符串。
        /// 常用于获取文件扩展名、后缀处理、字符串解析等场景。
        /// </remarks>
        public static string Right(this string? value, int length)
        {
            if (value.IsEmpty() || length <= 0)
                return string.Empty;

            return value!.Length <= length ? value : value[^length..];
        }

        /// <summary>
        /// 将字符串转换为标题格式（每个单词的首字母大写）。
        /// </summary>
        /// <param name="value">要转换的字符串。</param>
        /// <returns>
        /// 标题格式的字符串。如果输入为null或空，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "hello world";
        /// string title = text.ToTitleCase(); // 返回 "Hello World"
        /// 
        /// string mixed = "tHIS iS a TeST";
        /// string titleMixed = mixed.ToTitleCase(); // 返回 "This Is A Test"
        /// 
        /// // 格式化标题
        /// string articleTitle = "artificial intelligence in modern world";
        /// string formatted = articleTitle.ToTitleCase(); // "Artificial Intelligence In Modern World"
        /// 
        /// // 处理姓名
        /// string name = "john smith";
        /// string properName = name.ToTitleCase(); // "John Smith"
        /// </code>
        /// </example>
        /// <remarks>
        /// 使用当前区域设置的文化信息进行转换。
        /// 对于英文文本效果最佳，其他语言可能需要特殊处理。
        /// 常用于标题格式化、姓名规范化、显示文本美化等场景。
        /// </remarks>
        public static string ToTitleCase(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            var textInfo = System.Globalization.CultureInfo.CurrentCulture.TextInfo;
            return textInfo.ToTitleCase(value!.ToLowerInvariant());
        }

        #endregion

        #region 显示文本处理
        /// <summary>
        /// 将字符串转换为显示文本，当字符串为指定的无效值时返回默认显示文本。
        /// </summary>
        /// <param name="value">要检查的字符串。</param>
        /// <param name="invalidValues">被视为无效的值数组。</param>
        /// <param name="defaultDisplayText">当值无效时显示的文本，默认为"暂无数据"。</param>
        /// <returns>显示文本或默认文本。</returns>
        /// <example>
        /// <code>
        /// string birth = "0000-00-00 00:00:00";
        /// string displayText = birth.ToDisplayText(["0000-00-00 00:00:00"], "暂无数据");
        /// // 返回 "暂无数据"
        /// </code>
        /// </example>
        public static string ToDisplayText(this string? value, string[] invalidValues, string defaultDisplayText)
        {
            if (value.IsEmpty() || invalidValues.Contains(value))
                return defaultDisplayText;
            return value!;
        }
        /// <summary>
        /// 将字符串转换为显示文本，当字符串为指定的单个无效值时返回默认显示文本。
        /// </summary>
        /// <param name="value">要检查的字符串。</param>
        /// <param name="invalidValue">被视为无效的值。</param>
        /// <param name="defaultDisplayText">当值无效时显示的文本，默认为"暂无数据"。</param>
        /// <returns>显示文本或默认文本。</returns>
        public static string ToDisplayText(this string? value, string invalidValue, string defaultDisplayText)
        {
            if (value.IsEmpty() || value == invalidValue)
                return defaultDisplayText;
            return value!;
        }
        /// <summary>
        /// 将日期字符串转换为友好的显示文本，自动处理常见的无效日期格式。
        /// </summary>
        /// <param name="dateString">日期字符串。</param>
        /// <param name="defaultDisplayText">当日期无效时显示的文本，默认为"暂无数据"。</param>
        /// <param name="format">日期显示格式，默认为"yyyy-MM-dd"。</param>
        /// <returns>格式化的日期显示文本或默认文本。</returns>
        public static string ToDateDisplayText(this string? dateString, string defaultDisplayText = "暂无数据", string format = "yyyy-MM-dd")
        {
            if (dateString.IsEmpty())
                return defaultDisplayText;

            // 常见的无效日期格式
            string[] invalidDates = [
                "0000-00-00",
                "0000-00-00 00:00:00",
                "1900-01-01",
                "1900-01-01 00:00:00",
                "0001-01-01",
                "0001-01-01 00:00:00"
            ];

            if (invalidDates.Any(invalid => dateString!.StartsWith(invalid)))
                return defaultDisplayText;

            // 尝试解析并格式化日期
            if (DateTime.TryParse(dateString, out DateTime date) && date > DateTime.MinValue.AddYears(1900))
            {
                return date.ToString(format);
            }

            return defaultDisplayText;
        }

        /// <summary>
        /// 格式化数字为带千位分隔符的显示文本（整数显示）。
        /// </summary>
        /// <param name="value">数字字符串。</param>
        /// <param name="defaultText">转换失败时的默认文本，默认为"0"。</param>
        /// <returns>格式化后的数字文本。</returns>
        /// <example>
        /// <code>
        /// string number1 = "1234567";
        /// string number2 = "1234567.89";
        /// string number3 = null;
        /// string number4 = "abc";
        /// 
        /// string result1 = number1.ToFormattedNumber();        // 返回 "1,234,567"
        /// string result2 = number2.ToFormattedNumber();        // 返回 "1,234,568" (四舍五入)
        /// string result3 = number3.ToFormattedNumber();        // 返回 "0"
        /// string result4 = number4.ToFormattedNumber("N/A");   // 返回 "N/A"
        /// </code>
        /// </example>
        public static string ToFormattedNumber(this string? value, string defaultText)
        {
            return ToFormattedNumber(value, 0, defaultText);
        }

        /// <summary>
        /// 格式化数字为带千位分隔符的显示文本（指定小数位数）。
        /// </summary>
        /// <param name="value">数字字符串。</param>
        /// <param name="decimals">小数位数，范围0-29。</param>
        /// <param name="defaultText">转换失败时的默认文本，默认为"0"。</param>
        /// <returns>格式化后的数字文本。</returns>
        /// <example>
        /// <code>
        /// string number1 = "1234567.89123";
        /// string number2 = "1234567";
        /// string number3 = "1234567.1";
        /// string number4 = null;
        /// 
        /// string result1 = number1.ToFormattedNumber(2);       // 返回 "1,234,567.89"
        /// string result2 = number1.ToFormattedNumber(3);       // 返回 "1,234,567.891"
        /// string result3 = number2.ToFormattedNumber(2);       // 返回 "1,234,567.00"
        /// string result4 = number3.ToFormattedNumber(2);       // 返回 "1,234,567.10"
        /// string result5 = number4.ToFormattedNumber(2, "--"); // 返回 "--"
        /// </code>
        /// </example>
        public static string ToFormattedNumber(this string? value, int decimals, string defaultText)
        {
            if (value.IsEmpty())
                return defaultText;

            if (decimal.TryParse(value, out decimal number))
            {
                return number.ToString($"N{decimals}");
            }

            return defaultText;
        }

        /// <summary>
        /// 格式化数字为指定格式的显示文本。
        /// </summary>
        /// <param name="value">数字字符串。</param>
        /// <param name="format">数字格式字符串（如：N2、C2、P2、F2、#,##0.00等）。</param>
        /// <param name="defaultText">转换失败时的默认文本，默认为"0"。</param>
        /// <returns>格式化后的数字文本。</returns>
        /// <example>
        /// <code>
        /// string number = "1234567.89";
        /// 
        /// // 标准数字格式
        /// string formatted1 = number.ToFormattedNumber("N0");       // 返回 "1,234,568"
        /// string formatted2 = number.ToFormattedNumber("N2");       // 返回 "1,234,567.89"
        /// string formatted3 = number.ToFormattedNumber("N4");       // 返回 "1,234,567.8900"
        /// 
        /// // 货币格式
        /// string formatted4 = number.ToFormattedNumber("C0");       // 返回 "¥1,234,568"
        /// string formatted5 = number.ToFormattedNumber("C2");       // 返回 "¥1,234,567.89"
        /// 
        /// // 百分比格式
        /// string percent = "0.1234";
        /// string formatted6 = percent.ToFormattedNumber("P2");      // 返回 "12.34%"
        /// 
        /// // 固定小数点格式
        /// string formatted7 = number.ToFormattedNumber("F2");       // 返回 "1234567.89"
        /// string formatted8 = number.ToFormattedNumber("F0");       // 返回 "1234568"
        /// 
        /// // 自定义格式
        /// string formatted9 = number.ToFormattedNumber("#,##0.00"); // 返回 "1,234,567.89"
        /// string formatted10 = number.ToFormattedNumber("0.00");    // 返回 "1234567.89"
        /// 
        /// // 异常情况
        /// string invalid = "abc";
        /// string formatted11 = invalid.ToFormattedNumber("N2", "无效"); // 返回 "无效"
        /// </code>
        /// </example>
        public static string ToFormattedNumber(this string? value, string format, string defaultText)
        {
            if (value.IsEmpty())
                return defaultText;

            if (decimal.TryParse(value, out decimal number))
            {
                try
                {
                    return number.ToString(format);
                }
                catch (FormatException)
                {
                    // 如果格式字符串无效，回退到默认格式
                    return number.ToString("N0");
                }
            }

            return defaultText;
        }

        /// <summary>
        /// 格式化文件大小为人类可读的显示文本。
        /// </summary>
        /// <param name="value">文件大小字符串（字节数）。</param>
        /// <param name="defaultText">转换失败时的默认文本，默认为"0 B"。</param>
        /// <returns>格式化后的文件大小文本。</returns>
        /// <example>
        /// <code>
        /// string size = "1048576";
        /// string readable = size.ToReadableFileSize(); // 返回 "1.00 MB"
        /// </code>
        /// </example>
        public static string ToReadableFileSize(this string? value, string defaultText = "0 B")
        {
            if (value.IsEmpty() || !long.TryParse(value, out long bytes))
                return defaultText;

            return ToReadableFileSize(bytes);
        }
        /// <summary>
        /// 格式化文件大小为人类可读的显示文本。
        /// </summary>
        /// <param name="bytes">文件大小（字节数）。</param>
        /// <returns>格式化后的文件大小文本。</returns>
        public static string ToReadableFileSize(this long bytes)
        {
            string[] sizes = ["B", "KB", "MB", "GB", "TB", "PB"];
            double len = bytes;
            int order = 0;

            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }

            return $"{len:0.##} {sizes[order]}";
        }
        /// <summary>
        /// 条件格式化文本，根据条件返回不同的显示文本。
        /// </summary>
        /// <param name="value">要检查的值。</param>
        /// <param name="condition">判断条件。</param>
        /// <param name="trueText">条件为真时的显示文本。</param>
        /// <param name="falseText">条件为假时的显示文本。</param>
        /// <returns>根据条件返回的显示文本。</returns>
        /// <example>
        /// <code>
        /// string status = "1";
        /// string display = status.ConditionalText(s => s == "1", "启用", "禁用");
        /// // 返回 "启用"
        /// </code>
        /// </example>
        public static string ConditionalText(this string? value, Func<string?, bool> condition, string trueText, string falseText)
        {
            return condition(value) ? trueText : falseText;
        }
        /// <summary>
        /// 根据枚举值获取友好的显示文本。
        /// </summary>
        /// <param name="value">枚举值字符串。</param>
        /// <param name="displayMappings">显示映射字典。</param>
        /// <param name="defaultText">未找到映射时的默认文本。</param>
        /// <returns>友好的显示文本。</returns>
        /// <example>
        /// <code>
        /// var statusMappings = new Dictionary&lt;string, string&gt;
        /// {
        ///     {"0", "禁用"},
        ///     {"1", "启用"},
        ///     {"2", "维护中"}
        /// };
        /// string status = "1";
        /// string display = status.ToFriendlyText(statusMappings); // 返回 "启用"
        /// </code>
        /// </example>
        public static string ToFriendlyText(this string? value, Dictionary<string, string> displayMappings, string defaultText = "未知")
        {
            if (value.IsEmpty())
                return defaultText;

            return displayMappings.TryGetValue(value!, out string? friendlyText) ? friendlyText : defaultText;
        }
        #endregion

        #region 数据提取

        /// <summary>
        /// 从字符串中提取所有数字字符，忽略非数字字符(也可以更直接的使用ToInt或ToLong)。
        /// </summary>
        /// <param name="value">要处理的字符串。</param>
        /// <returns>提取出的数字字符串，如果没有数字则返回空字符串。</returns>
        /// <example>
        /// <code>
        /// string text = "abc123def456";
        /// string result = text.ExtractDigits(); // 返回 "123456"
        /// </code>
        /// </example>
        public static string ExtractDigits(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;
            var digits = new StringBuilder();
            foreach (char c in value!)
            {
                if (char.IsDigit(c))
                    digits.Append(c);
            }
            return digits.ToString();
        }

        #endregion

        //这里后面移动到其他命名空间中
        #region HTML处理

        /// <summary>
        /// 用于移除HTML标签的正则表达式。
        /// </summary>
        /// <returns>用于匹配HTML标签的 <see cref="Regex"/> 实例。</returns>
        /// <remarks>
        /// 匹配所有HTML标签，包括自闭合标签和带属性的标签。
        /// </remarks>
        [GeneratedRegex(@"<[^>]*>")]
        private static partial Regex HtmlTagRegex();

        /// <summary>
        /// 移除字符串中的所有HTML标签，保留纯文本内容。
        /// </summary>
        /// <param name="value">包含HTML标签的字符串。</param>
        /// <returns>
        /// 移除HTML标签后的纯文本字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string html = "<div><p>Hello <strong>World</strong>!</p></div>";
        /// string text = html.RemoveHtml(); // 返回 "Hello World!"
        /// 
        /// string withAttributes = "<a href='#' class='link'>Click me</a>";
        /// string clean = withAttributes.RemoveHtml(); // 返回 "Click me"
        /// 
        /// string noHtml = "Pure text content";
        /// string result = noHtml.RemoveHtml(); // 返回 "Pure text content"
        /// 
        /// string selfClosing = "<img src='image.jpg' alt='test' />Content";
        /// string cleaned = selfClosing.RemoveHtml(); // 返回 "Content"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法使用编译时生成的正则表达式，在AOT编译场景下具有更好的性能和兼容性。
        /// 适用于简单的HTML清理需求，能够移除所有HTML标签（包括带属性的标签）。
        /// 对于复杂的HTML解析和处理需求，建议使用专业的HTML解析库如HtmlAgilityPack。
        /// 注意：此方法不会解码HTML实体（如&amp;lt;、&amp;gt;、&amp;amp;等），如需要可以结合HttpUtility.HtmlDecode使用。
        /// </remarks>
        public static string RemoveHtml(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return HtmlTagRegex().Replace(value!, string.Empty);
        }

        /// <summary>
        /// 对字符串进行HTML编码，将特殊字符转换为HTML实体。
        /// </summary>
        /// <param name="value">要编码的字符串。</param>
        /// <returns>
        /// HTML编码后的字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string text = "Hello &lt;World&gt; &amp; \"Friends\"";
        /// string encoded = text.HtmlEncode(); // 返回 "Hello &amp;lt;World&amp;gt; &amp;amp; &amp;quot;Friends&amp;quot;"
        /// 
        /// string userInput = "&lt;script&gt;alert('xss')&lt;/script&gt;";
        /// string safe = userInput.HtmlEncode(); // 防XSS攻击
        /// 
        /// // 显示用户输入内容
        /// string comment = user.Comment;
        /// string safeComment = comment.HtmlEncode();
        /// </code>
        /// </example>
        /// <remarks>
        /// 将HTML特殊字符(&lt;, &gt;, &amp;, ", ')转换为对应的HTML实体。
        /// 主要用于防止XSS攻击，确保用户输入安全显示在网页上。
        /// 适用于Web开发、HTML内容生成、用户输入处理等场景。
        /// </remarks>
        public static string HtmlEncode(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return System.Web.HttpUtility.HtmlEncode(value!);
        }

        /// <summary>
        /// 对HTML编码的字符串进行解码，将HTML实体转换回原始字符。
        /// </summary>
        /// <param name="value">要解码的HTML编码字符串。</param>
        /// <returns>
        /// HTML解码后的字符串。如果输入为null或空字符串，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string encoded = "Hello &amp;lt;World&amp;gt; &amp;amp; &amp;quot;Friends&amp;quot;";
        /// string decoded = encoded.HtmlDecode(); // 返回 "Hello &lt;World&gt; &amp; \"Friends\""
        /// 
        /// string htmlEntity = "&amp;copy; 2024 Company Name";
        /// string text = htmlEntity.HtmlDecode(); // 返回 "© 2024 Company Name"
        /// 
        /// // 处理从HTML页面提取的文本
        /// string htmlContent = "&amp;lt;p&amp;gt;Content&amp;lt;/p&amp;gt;";
        /// string plainText = htmlContent.HtmlDecode();
        /// </code>
        /// </example>
        /// <remarks>
        /// 将HTML实体(&amp;lt;, &amp;gt;, &amp;amp;, &amp;quot;, &amp;#39;等)转换回对应的字符。
        /// 常用于处理从HTML页面、XML文档中提取的文本内容。
        /// 适用于数据解析、内容提取、文本处理等场景。
        /// </remarks>
        public static string HtmlDecode(this string? value)
        {
            if (value.IsEmpty())
                return string.Empty;

            return System.Web.HttpUtility.HtmlDecode(value!);
        }

        #endregion

        //这里后面移动到其他命名空间中
        #region 路径和文件处理

        /// <summary>
        /// 获取文件路径的完整绝对路径。
        /// </summary>
        /// <param name="path">文件或目录路径。</param>
        /// <returns>
        /// 完整的绝对路径。如果输入路径无效或为空，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string relativePath = "docs/readme.txt";
        /// string fullPath = relativePath.GetFullPath(); // 返回 "C:\Users\Username\Project\docs\readme.txt"
        /// 
        /// string currentDir = ".";
        /// string full = currentDir.GetFullPath(); // 返回当前目录的完整路径
        /// 
        /// string fileName = "config.json";
        /// string absolutePath = fileName.GetFullPath(); // 返回 "C:\Users\Username\Project\config.json"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetFullPath实现，会解析相对路径为绝对路径。
        /// 如果路径不存在，仍会返回计算出的绝对路径，不会验证路径是否实际存在。
        /// 适用于路径标准化、相对路径转换等场景。
        /// </remarks>
        public static string GetFullPath(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetFullPath(path!);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取路径中的驱动器盘符（Windows系统）或根目录（Unix系统）。
        /// </summary>
        /// <param name="path">文件或目录路径。</param>
        /// <returns>
        /// 驱动器盘符（如"C:"）或根目录。如果路径无效或不包含盘符，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string windowsPath = @"C:\Users\Username\Documents\file.txt";
        /// string drive = windowsPath.GetPathRoot(); // 返回 "C:\"
        /// 
        /// string unixPath = "/home/user/documents/file.txt";
        /// string root = unixPath.GetPathRoot(); // 返回 "/"
        /// 
        /// string relativePath = "docs/readme.txt";
        /// string noDrive = relativePath.GetPathRoot(); // 返回 ""
        /// 
        /// string networkPath = @"\\server\share\file.txt";
        /// string networkRoot = networkPath.GetPathRoot(); // 返回 "\\server\share"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetPathRoot实现，跨平台兼容。
        /// Windows系统返回盘符（如"C:\"），Unix系统返回根目录"/"。
        /// 对于网络路径，会返回服务器和共享名部分。
        /// </remarks>
        public static string GetPathRoot(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetPathRoot(path!) ?? string.Empty;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取路径中的文件名（包含扩展名）。
        /// </summary>
        /// <param name="path">文件路径。</param>
        /// <returns>
        /// 文件名（包含扩展名）。如果路径为目录或无效，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string filePath = @"C:\Users\Username\Documents\report.pdf";
        /// string fileName = filePath.GetFileName(); // 返回 "report.pdf"
        /// 
        /// string pathWithoutExt = @"/home/user/docs/readme";
        /// string name = pathWithoutExt.GetFileName(); // 返回 "readme"
        /// 
        /// string directoryPath = @"C:\Users\Username\Documents\";
        /// string dirName = directoryPath.GetFileName(); // 返回 ""
        /// 
        /// string relativePath = "config.json";
        /// string relativeFileName = relativePath.GetFileName(); // 返回 "config.json"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetFileName实现，跨平台兼容。
        /// 如果路径以目录分隔符结尾，会被认为是目录路径，返回空字符串。
        /// 适用于从完整路径中提取文件名的场景。
        /// </remarks>
        public static string GetFileName(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetFileName(path!) ?? string.Empty;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取路径中的文件名（不包含扩展名）。
        /// </summary>
        /// <param name="path">文件路径。</param>
        /// <returns>
        /// 文件名（不包含扩展名）。如果路径为目录或无效，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string filePath = @"C:\Users\Username\Documents\report.pdf";
        /// string nameWithoutExt = filePath.GetFileNameWithoutExtension(); // 返回 "report"
        /// 
        /// string multiExtPath = "archive.tar.gz";
        /// string name = multiExtPath.GetFileNameWithoutExtension(); // 返回 "archive.tar"
        /// 
        /// string noExtPath = "README";
        /// string plainName = noExtPath.GetFileNameWithoutExtension(); // 返回 "README"
        /// 
        /// string hiddenFile = ".gitignore";
        /// string hiddenName = hiddenFile.GetFileNameWithoutExtension(); // 返回 ".gitignore"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetFileNameWithoutExtension实现。
        /// 对于多重扩展名（如.tar.gz），只会移除最后一个扩展名。
        /// 对于隐藏文件（以.开头且无其他扩展名），会返回完整的文件名。
        /// </remarks>
        public static string GetFileNameWithoutExtension(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetFileNameWithoutExtension(path!) ?? string.Empty;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取文件的扩展名（包含点号）。
        /// </summary>
        /// <param name="path">文件路径。</param>
        /// <returns>
        /// 文件扩展名（包含点号，如".txt"）。如果文件没有扩展名或路径无效，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string filePath = @"C:\Users\Username\Documents\report.pdf";
        /// string extension = filePath.GetExtension(); // 返回 ".pdf"
        /// 
        /// string imageFile = "photo.jpeg";
        /// string imgExt = imageFile.GetExtension(); // 返回 ".jpeg"
        /// 
        /// string noExtFile = "README";
        /// string noExt = noExtFile.GetExtension(); // 返回 ""
        /// 
        /// string hiddenFile = ".gitignore";
        /// string hiddenExt = hiddenFile.GetExtension(); // 返回 ""
        /// 
        /// string multiExt = "archive.tar.gz";
        /// string lastExt = multiExt.GetExtension(); // 返回 ".gz"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetExtension实现。
        /// 返回的扩展名包含点号，如".txt"、".pdf"等。
        /// 对于多重扩展名文件，只返回最后一个扩展名。
        /// 隐藏文件（仅以点号开头）不被视为有扩展名。
        /// </remarks>
        public static string GetExtension(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetExtension(path!) ?? string.Empty;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取路径中的目录部分。
        /// </summary>
        /// <param name="path">文件或目录路径。</param>
        /// <returns>
        /// 路径中的目录部分。如果路径无效或为根目录，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string filePath = @"C:\Users\Username\Documents\report.pdf";
        /// string directory = filePath.GetDirectoryName(); // 返回 "C:\Users\Username\Documents"
        /// 
        /// string dirPath = @"/home/user/projects/myapp/";
        /// string parentDir = dirPath.GetDirectoryName(); // 返回 "/home/user/projects/myapp"
        /// 
        /// string rootPath = @"C:\";
        /// string rootDir = rootPath.GetDirectoryName(); // 返回 ""
        /// 
        /// string relativePath = "docs/readme.txt";
        /// string relativeDir = relativePath.GetDirectoryName(); // 返回 "docs"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.GetDirectoryName实现，跨平台兼容。
        /// 对于根目录路径，会返回null（此扩展方法转换为空字符串）。
        /// 返回的路径不包含尾随的目录分隔符。
        /// </remarks>
        public static string GetDirectoryName(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                return Path.GetDirectoryName(path!) ?? string.Empty;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 组合多个路径字符串为一个完整的路径。
        /// </summary>
        /// <param name="path1">第一个路径部分。</param>
        /// <param name="paths">要组合的其他路径部分。</param>
        /// <returns>
        /// 组合后的完整路径。如果任何路径部分无效，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// string basePath = @"C:\Users\Username";
        /// string combinedPath = basePath.CombinePath("Documents", "Projects", "MyApp");
        /// // 返回 "C:\Users\Username\Documents\Projects\MyApp"
        /// 
        /// string rootPath = "/home/user";
        /// string unixPath = rootPath.CombinePath("projects", "webapp", "src");
        /// // 返回 "/home/user/projects/webapp/src"
        /// 
        /// string currentDir = ".";
        /// string relativePath = currentDir.CombinePath("config", "app.json");
        /// // 返回 "./config/app.json" 或 ".\config\app.json"（取决于平台）
        /// 
        /// // 处理空路径部分
        /// string result = "base".CombinePath("", "middle", "", "end");
        /// // 返回 "base/middle/end" 或 "base\middle\end"
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法内部使用Path.Combine实现，会自动处理不同平台的路径分隔符。
        /// 空的路径部分会被忽略，不会影响最终结果。
        /// 如果后续路径是绝对路径，会替换之前的所有路径部分。
        /// 适用于动态构建文件路径、配置文件路径等场景。
        /// </remarks>
        public static string CombinePath(this string? path1, params string[] paths)
        {
            if (path1.IsEmpty() && (paths == null || paths.Length == 0))
                return string.Empty;

            try
            {
                var allPaths = new List<string>();
                if (!path1.IsEmpty())
                    allPaths.Add(path1!);
                if (paths != null)
                    allPaths.AddRange(paths.Where(p => !string.IsNullOrEmpty(p)));

                if (allPaths.Count == 0)
                    return string.Empty;

                return Path.Combine([.. allPaths]);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 将路径中的无效字符替换为指定字符。
        /// </summary>
        /// <param name="path">要清理的路径。</param>
        /// <param name="replacement">用于替换无效字符的字符，默认为下划线'_'。</param>
        /// <remarks>
        /// 此方法会替换Path.GetInvalidPathChars()中定义的所有无效字符。
        /// 适用于清理用户输入的文件名或路径，确保可以安全地用于文件系统操作。
        /// 注意：此方法不区分路径和文件名，如需要更精确的处理，建议分别使用路径和文件名的清理方法。
        /// </remarks>
        public static string SanitizePath(this string? path, char replacement = '_')
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                var invalidChars = Path.GetInvalidPathChars();
                var result = path!;
                foreach (char c in invalidChars)
                {
                    result = result.Replace(c, replacement);
                }
                return result;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 将文件名中的无效字符替换为指定字符。
        /// </summary>
        /// <param name="fileName">要清理的文件名。</param>
        /// <param name="replacement">用于替换无效字符的字符，默认为下划线'_'。</param>
        /// <remarks>
        /// 此方法会替换Path.GetInvalidFileNameChars()中定义的所有无效字符。
        /// 文件名的无效字符比路径更严格，包括路径分隔符、引号等。
        /// 适用于清理用户输入的文件名，确保可以安全地用于文件创建操作。
        /// </remarks>
        public static string SanitizeFileName(this string? fileName, char replacement = '_')
        {
            if (fileName.IsEmpty())
                return string.Empty;

            try
            {
                var invalidChars = Path.GetInvalidFileNameChars();
                var result = fileName!;
                foreach (char c in invalidChars)
                {
                    result = result.Replace(c, replacement);
                }
                return result;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 标准化路径分隔符，将路径中的分隔符统一为当前平台的标准分隔符。
        /// </summary>
        /// <param name="path">要标准化的路径。</param>
        /// <returns>
        /// 标准化后的路径。如果输入为空，则返回空字符串。
        /// </returns>
        /// <example>
        /// <code>
        /// // 在Windows平台上：
        /// string mixedPath = "C:/Users/Username\\Documents/file.txt";
        /// string normalized = mixedPath.NormalizePath();
        /// // 返回 "C:\Users\Username\Documents\file.txt"
        /// 
        /// // 在Unix平台上：
        /// string windowsPath = @"home\user\documents\file.txt";
        /// string unixNormalized = windowsPath.NormalizePath();
        /// // 返回 "home/user/documents/file.txt"
        /// 
        /// string alreadyNormal = "/home/user/file.txt";
        /// string unchanged = alreadyNormal.NormalizePath();
        /// // 返回 "/home/user/file.txt"（在Unix上不变）
        /// </code>
        /// </example>
        /// <remarks>
        /// 此方法会将所有路径分隔符（'/' 和 '\'）替换为当前平台的标准分隔符。
        /// Windows平台使用反斜杠'\'，Unix平台使用正斜杠'/'。
        /// 适用于处理跨平台路径、标准化用户输入的路径等场景。
        /// </remarks>
        public static string NormalizePath(this string? path)
        {
            if (path.IsEmpty())
                return string.Empty;

            try
            {
                // 将所有路径分隔符替换为当前平台的标准分隔符
                return path!.Replace('/', Path.DirectorySeparatorChar)
                           .Replace('\\', Path.DirectorySeparatorChar);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        #endregion
    }
}
